package server

import (
	"fmt"
	kratosHttp "github.com/go-kratos/kratos/v2/transport/http"
	kratosStatus "github.com/go-kratos/kratos/v2/transport/http/status"
	"google.golang.org/grpc/status"
	"net/http"
)

// httpResponse 自定义http响应格式
type httpResponse struct {
	Code int    `json:"code"`
	Msg  string `json:"msg"`
	Data any    `json:"data"`
}

// 自定义编码器
func responseEncode(w http.ResponseWriter, r *http.Request, v interface{}) error {
	if v == nil {
		return nil
	}
	if rd, ok := v.(kratosHttp.Redirector); ok {
		url, code := rd.Redirect()
		http.Redirect(w, r, url, code)
		return nil
	}
	//搞一个自定义的格式
	resp := &httpResponse{
		Code: 200,
		Msg:  "success",
		Data: v,
	}

	// 前端请求头的内容实例
	// --header 'Accept: application/json' 声明响应结构体格式
	codec, _ := kratosHttp.CodecForRequest(r, "Accept")
	data, err := codec.Marshal(resp) // 解析出来的 codec 是个接口，比如返回的json，那么就是 json.Marshal
	if err != nil {
		return err
	}
	w.Header().Set("Content-Type", fmt.Sprintf("application/%s", codec.Name()))
	_, err = w.Write(data)
	if err != nil {
		return err
	}
	return nil
}

// 自定义处理错误编码
func errEncoder(w http.ResponseWriter, r *http.Request, err error) {

	if err == nil {
		return
	}
	resp := &httpResponse{
		Code: 0,
		Msg:  "内部错误",
		Data: nil,
	}
	//查看是否能从 grp的 err解析处理 状态码
	if grpcCode, ok := status.FromError(err); ok {
		resp.Code = kratosStatus.FromGRPCCode(grpcCode.Code())
		resp.Msg = grpcCode.Message()
	} else {
		resp.Code = http.StatusInternalServerError
		resp.Msg = err.Error()
	}

	codec, _ := kratosHttp.CodecForRequest(r, "Accept")
	body, err := codec.Marshal(resp)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	w.Header().Set("Content-Type", fmt.Sprintf("application/%s", codec.Name()))
	w.WriteHeader(resp.Code)
	_, _ = w.Write(body)
}
